// this
var a = 10; // 全局变量
// 题1
function Test1() {
  function foo() {
    console.log(this.a);
    // console.log(a); // 2
  }
  function doFoo() {
    foo();
  }
  var obj = {
    a: 1,
    doFoo,
  };
  var a = 2;
  obj.doFoo();
}
// Test1()
// 结果： 10
//
/**
 * 解析：当前的this是window
 *
 *
 */

// 题2
function Test2() {
  var obj = {
    a: 20,
    say: () => {
      console.log(this.a);
    },
  };
  obj.say();
  var anotherObj = { a: 30 };
  obj.say.apply(anotherObj);
}
// Test2()
// 结果：
// 10
// 10
//
/**
 * 解析：箭头函数，当前的this是window
 *
 */

// 题3
function Test3() {
  function a() {
    console.log(this);
  }
  a.call(null);
}
// Test3()
// 结果：window
//
/**
 * 解析：严格模式中null就是null，undefined就是undefined
 *
 */

// 题4
function Test4() {
  var obj = {
    name: "abin",
    func: function () {
      console.log(this.name);
    },
  };
  obj.func();
  new obj.func();
}
// Test4()
// 结果：
// abin
// undefined
//
//
/**
 * 解析：
 *
 */

// 题5
function Test5() {
  var obj = {
    say: function () {
      var f1 = () => {
        console.log(this);
      };
      f1();
    },
    pro: {
      getPro: () => {
        console.log(this);
      },
    },
  };
  var o = obj.say;
  o();
  obj.say();
  obj.pro.getPro();
}
// Test5()
// 结果：
// window
// obj
// window
/**
 * 解析：
 * o在全局执行，父级say的this指向全局作用域
 * obj.say执行时，say的this指向obj
 * obj.pro.getPro执行时，对象不构成作用域，this指向了全局作用域
 */

// 题6
function Test6() {
  var myObject = {
    foo: "bar",
    func: function () {
      var self = this;
      console.log(this.foo);
      console.log(self.foo);
      (function () {
        console.log(this.foo);
        console.log(self.foo);
      })();
    },
  };
  myObject.func();
}
// Test6()
// 结果：
// bar
// bar
// undefined
// bar
/**
 * 解析：
 * 立即执行函数的表达式是由window调用的，this指向了window
 * self变量沿着作用域链向上查找，找到了self
 */

// 题7
function Test7() {
  window.number = 2;
  var obj = {
    number: 3,
    db1: (function () {
      console.log(this);
      this.number *= 4;
      return function () {
        console.log(this);
        this.number *= 5;
      };
    })(),
  };
  var db1 = obj.db1;
  db1();
  obj.db1();
  console.log(obj.number);
  console.log(window.number);
}
// Test7()
// 结果：
// window
// window
// obj
// 15
// 40
/**
 * 解析：
 *
 */
var length = 10; // 全局变量
// 题8
function Test8() {
  function fn() {
    console.log(this.length);
  }
  var obj = {
    length: 5,
    method: function (fn) {
      fn();
      arguments[0]();
    },
  };
  obj.method(fn, 1);
}
// Test8()
// 结果：
//
/**
 * 解析：
 * 第一次fn执行，this指向window
 * 第二次arguments，this指向arguments，这里两个参数，所以长度为2
 */

// 题9
function Test9() {
  var a = 1;
  function printA() {
    console.log(this.a);
  }
  var obj = {
    a: 2,
    foo: printA,
    bar: function () {
      printA();
    },
  };
  obj.foo();
  obj.bar();
  var foo = obj.foo;
  foo();
}
// Test9()
// 结果：
// 2
// 10
// 10
/**
 * 解析：
 *
 */
var x = 3;
var y = 4;
// 题10
function Test10() {
  var obj = {
    x: 1,
    y: 6,
    getX: function () {
      var x = 5;
      return (function () {
        return this.x;
      })();
    },
    getY: function () {
      var y = 7;
      return this.y;
    },
  };
  console.log(obj.getX());
  console.log(obj.getY());
}
// Test10()
// 结果：
// 3
// 6
/**
 * 解析：
 * 匿名函数的this指向全局对象，所以this指向window
 */

// 题11
var a = 10;
function Test11() {
  var obj = {
    a: 20,
    fn: function () {
      var a = 30;
      console.log(this.a);
    },
  };
  obj.fn();
  obj.fn.call();
  (obj.fn)();
}
// Test11();
// 结果：
// 20
// 10
// 20
/**
 * 解析：
 * 第二个，call没有参数，this指向window
 * 第三个，括号只是表明优先级，对结果没有影响
 */


// 题12
function Test12() {
   function foo(something) {
     this.a = something
   }
   var obj1 = {
     foo
   }

   var obj2 = {}

   obj1.foo(2) 
   console.log(obj1.a);
   obj1.foo.call(obj2, 3)
   console.log(obj2.a);

   var bar  = new obj1.foo(4)
   console.log(obj1.a);
   console.log(bar.a);
   var bindFn = obj1.foo.bind(obj2)
   bindFn(7)
   var bar2 = new bindFn(8)
   console.log(obj2.a);
   console.log(bar2.a);
   
}
Test12()
// 结果：
// 2
// 3
// 2
// 4
// 7
// 8
/**
 * 解析：this绑定的优先级: new绑定 > 显式绑定 > 隐式绑定 > 默认绑定
 * 
 */

